package com.example.webrtcdemo.webrtc

import android.util.Log
import org.json.JSONObject
import org.webrtc.DataChannel
import java.nio.ByteBuffer
import java.nio.charset.StandardCharsets
import java.util.Timer
import java.util.TimerTask
import java.util.concurrent.ConcurrentHashMap

/**
 * @作者: smile
 * @时间: 2025/10/9 20:48
 * @描述:
 **/
class P2PMessageManager(private val dataChannel: DataChannel?) {
    private val TAG = "P2PMessageManager"
    private var messageIdCounter = 0
    private val pendingMessages = ConcurrentHashMap<String, PendingMessage>()

    // 消息类型枚举
    enum class MessageType {
        TEXT,           // 文本消息
        COMMAND,        // 控制命令
        ACK,            // 确认消息
        HEARTBEAT,      // 心跳
        FILE_META,      // 文件元数据
        FILE_CHUNK,     // 文件分片
        SYSTEM          // 系统消息
    }

    // 标准P2P消息格式
    data class P2PMessage(
        val id: String,
        val type: MessageType,
        val payload: String,
        val timestamp: Long = System.currentTimeMillis()
    ) {
        fun toJson(): String {
            return JSONObject().apply {
                put("id", id)
                put("type", type.name)
                put("payload", payload)
                put("timestamp", timestamp)
            }.toString()
        }

        companion object {
            fun fromJson(json: String): P2PMessage? {
                return try {
                    val jsonObject = JSONObject(json)
                    P2PMessage(
                        id = jsonObject.getString("id"),
                        type = MessageType.valueOf(jsonObject.getString("type")),
                        payload = jsonObject.getString("payload"),
                        timestamp = jsonObject.getLong("timestamp")
                    )
                } catch (e: Exception) {
                    null
                }
            }
        }
    }

    // 待确认消息
    private data class PendingMessage(
        val message: P2PMessage,
        val sendTime: Long,
        var retryCount: Int = 0,
        val callback: ((Boolean, String?) -> Unit)? = null
    )

    // 消息监听器
    interface MessageListener {
        fun onTextMessageReceived(message: String, messageId: String)
        fun onCommandMessageReceived(command: String, parameters: Map<String, Any>, messageId: String)
        fun onSystemMessageReceived(message: String)
        fun onMessageAckReceived(messageId: String)
        fun onMessageSendSuccess(messageId: String)
        fun onMessageSendFailed(messageId: String, error: String)
    }

    private var messageListener: MessageListener? = null

    /**
     * 发送文本消息
     */
    fun sendTextMessage(
        text: String,
        needAck: Boolean = true,
        timeout: Long = 5000,
        maxRetries: Int = 3,
        callback: ((Boolean, String?) -> Unit)? = null
    ): String? {
        return sendMessage(MessageType.TEXT, text, needAck, timeout, maxRetries, callback)
    }

    /**
     * 发送命令消息
     */
    fun sendCommandMessage(
        command: String,
        parameters: Map<String, Any> = emptyMap(),
        needAck: Boolean = true,
        timeout: Long = 5000,
        maxRetries: Int = 3,
        callback: ((Boolean, String?) -> Unit)? = null
    ): String? {
        val payload = JSONObject().apply {
            put("command", command)
            put("parameters", JSONObject(parameters))
        }.toString()

        return sendMessage(MessageType.COMMAND, payload, needAck, timeout, maxRetries, callback)
    }

    /**
     * 发送系统消息
     */
    fun sendSystemMessage(systemMsg: String): String? {
        return sendMessage(MessageType.SYSTEM, systemMsg, needAck = false)
    }

    /**
     * 发送心跳消息
     */
    fun sendHeartbeat(): String? {
        return sendMessage(MessageType.HEARTBEAT, "ping", needAck = false)
    }

    /**
     * 发送确认消息
     */
    private fun sendAckMessage(messageId: String): String? {
        return sendMessage(MessageType.ACK, messageId, needAck = false)
    }

    /**
     * 发送消息核心方法
     */
    private fun sendMessage(
        type: MessageType,
        payload: String,
        needAck: Boolean = true,
        timeout: Long = 5000,
        maxRetries: Int = 3,
        callback: ((Boolean, String?) -> Unit)? = null
    ): String? {
        val messageId = generateMessageId()
        val message = P2PMessage(messageId, type, payload)

        return if (sendRawMessage(message.toJson())) {
            // 如果需要确认，添加到待确认列表
            if (needAck && type != MessageType.ACK && type != MessageType.HEARTBEAT) {
                pendingMessages[messageId] = PendingMessage(
                    message = message,
                    sendTime = System.currentTimeMillis(),
                    callback = callback
                )

                // 设置超时检查
                if (timeout > 0) {
                    startTimeoutCheck(messageId, timeout, maxRetries)
                }
            } else {
                callback?.invoke(true, null)
                messageListener?.onMessageSendSuccess(messageId)
            }
            messageId
        } else {
            callback?.invoke(false, "发送失败")
            messageListener?.onMessageSendFailed(messageId, "发送失败")
            null
        }
    }

    /**
     * 发送原始消息到数据通道
     */
    private fun sendRawMessage(message: String): Boolean {
        val state = dataChannel?.state() ?: DataChannel.State.CLOSED

        return when (state) {
            DataChannel.State.OPEN -> {
                try {
                    val buffer = DataChannel.Buffer(
                        ByteBuffer.wrap(message.toByteArray(StandardCharsets.UTF_8)),
                        false // 文本消息
                    )
                    dataChannel?.send(buffer)
                    Log.d(TAG, "P2P消息发送成功: ${message.take(50)}...")
                    true
                } catch (e: Exception) {
                    Log.e(TAG, "P2P消息发送异常", e)
                    false
                }
            }
            DataChannel.State.CONNECTING -> {
                Log.w(TAG, "数据通道正在连接中，稍后重试")
                false
            }
            DataChannel.State.CLOSING, DataChannel.State.CLOSED -> {
                Log.e(TAG, "数据通道已关闭，无法发送消息")
                false
            }
            else -> {
                Log.e(TAG, "数据通道状态异常: $state")
                false
            }
        }
    }

    /**
     * 处理接收到的消息
     */
    fun handleReceivedMessage(message: String) {
        try {
            val p2pMessage = P2PMessage.fromJson(message)
            if (p2pMessage != null) {
                handleStandardMessage(p2pMessage)
            } else {
                // 处理非标准格式消息（兼容旧版本）
                handleRawMessage(message)
            }
        } catch (e: Exception) {
            Log.e(TAG, "处理P2P消息失败", e)
        }
    }

    /**
     * 处理标准格式消息
     */
    private fun handleStandardMessage(message: P2PMessage) {
        when (message.type) {
            MessageType.ACK -> {
                // 收到确认消息，移除待确认列表
                pendingMessages.remove(message.payload)
                Log.d(TAG, "收到消息确认: ${message.id}")
                messageListener?.onMessageAckReceived(message.payload)
            }
            MessageType.TEXT -> {
                // 发送确认消息
                sendAckMessage(message.id)
                // 通知上层处理文本消息
                messageListener?.onTextMessageReceived(message.payload, message.id)
            }
            MessageType.COMMAND -> {
                // 发送确认消息
                sendAckMessage(message.id)
                // 解析并处理命令消息
                handleCommandMessage(message)
            }
            MessageType.SYSTEM -> {
                messageListener?.onSystemMessageReceived(message.payload)
            }
            MessageType.HEARTBEAT -> {
                // 心跳消息，回复确认
                sendAckMessage(message.id)
                Log.d(TAG, "收到心跳消息: ${message.id}")
            }
            else -> {
                Log.w(TAG, "未知消息类型: ${message.type}")
            }
        }
    }

    /**
     * 处理命令消息
     */
    private fun handleCommandMessage(message: P2PMessage) {
        try {
            val jsonObject = JSONObject(message.payload)
            val command = jsonObject.getString("command")
            val parametersJson = jsonObject.getJSONObject("parameters")

            val parameters = HashMap<String, Any>()
            val keys = parametersJson.keys()
            while (keys.hasNext()) {
                val key = keys.next()
                parameters[key] = parametersJson.get(key)
            }

            messageListener?.onCommandMessageReceived(command, parameters, message.id)
        } catch (e: Exception) {
            Log.e(TAG, "解析命令消息失败", e)
        }
    }

    /**
     * 处理原始格式消息（兼容性）
     */
    private fun handleRawMessage(message: String) {
        Log.d(TAG, "收到原始格式消息: $message")
        // 将原始消息作为文本消息处理
        messageListener?.onTextMessageReceived(message, generateMessageId())
    }

    /**
     * 超时检查
     */
    private fun startTimeoutCheck(messageId: String, timeout: Long, maxRetries: Int) {
        Timer().schedule(object : TimerTask() {
            override fun run() {
                val pendingMessage = pendingMessages[messageId] ?: return

                if (pendingMessage.retryCount < maxRetries) {
                    // 重试发送
                    pendingMessage.retryCount++
                    Log.w(TAG, "消息超时，第${pendingMessage.retryCount}次重试: $messageId")

                    if (sendRawMessage(pendingMessage.message.toJson())) {
                        // 重新设置超时检查
                        startTimeoutCheck(messageId, timeout, maxRetries)
                    } else {
                        // 发送失败，最终失败
                        pendingMessages.remove(messageId)
                        pendingMessage.callback?.invoke(false, "重试发送失败")
                        messageListener?.onMessageSendFailed(messageId, "重试发送失败")
                    }
                } else {
                    // 达到最大重试次数，最终失败
                    pendingMessages.remove(messageId)
                    pendingMessage.callback?.invoke(false, "消息发送超时")
                    messageListener?.onMessageSendFailed(messageId, "消息发送超时")
                    Log.e(TAG, "消息发送最终失败: $messageId")
                }
            }
        }, timeout)
    }

    /**
     * 生成消息ID
     */
    private fun generateMessageId(): String {
        return "msg_${System.currentTimeMillis()}_${messageIdCounter++}"
    }

    /**
     * 设置消息监听器
     */
    fun setMessageListener(listener: MessageListener) {
        this.messageListener = listener
    }

    /**
     * 清理资源
     */
    fun dispose() {
        pendingMessages.clear()
        messageListener = null
    }

    /**
     * 获取待确认消息数量
     */
    fun getPendingMessageCount(): Int {
        return pendingMessages.size
    }

    /**
     * 获取数据通道状态
     */
    fun getDataChannelState(): DataChannel.State? {
        return dataChannel?.state()
    }
}